﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HotelDAO.DAO
{
    /// <summary>
    /// Interface for base DAO.
    /// </summary>
    /// <typeparam name="TE">The target entity type that this DAO will manipulate on</typeparam>
    /// <typeparam name="TK">The target entity key type</typeparam>
    public interface IBaseDAO<TE, TK>
    {
        /// <summary>
        /// Gets entity by the key.
        /// </summary>
        /// <param name="key">
        /// The specific key.
        /// </param>
        /// <returns>
        /// The matched entity.
        /// </returns>
        TE Get(TK key);

        /// <summary>
        /// Gets all entities
        /// </summary>
        /// <returns>The list of all entities</returns>
        IList<TE> GetAll();

        /// <summary>
        /// Save an entity to database.
        /// </summary>
        /// <param name="entity">
        /// The entity will be saved.
        /// </param>
        /// <returns>
        /// The key of the entity.
        /// </returns>
        TK Save(TE entity);

        /// <summary>
        /// Save or update an entity to database.
        /// </summary>
        /// <param name="entity">
        /// The entity will be saved/updated.
        /// </param>
        void SaveOrUpdate(TE entity);

        /// <summary>
        /// Save or update a list of entities.
        /// </summary>
        /// <param name="entities">
        /// The entity list.
        /// </param>
        void SaveOrUpdate(ICollection<TE> entities);


        /// <summary>
        /// Merge an entity to database.
        /// </summary>
        /// <param name="entity">
        /// The entity will be merge.
        /// </param>
        /// <returns>Entity object after merged</returns>
        TE Merge(TE entity);

        /// <summary>
        /// Merge a list of entities.
        /// </summary>
        /// <param name="entities">
        /// The entity list.
        /// </param>
        /// <returns>A list of entity object after merged</returns>
        ICollection<TE> Merge(ICollection<TE> entities);

        /// <summary>
        /// Find a list of matched entities by providing an hql and its parameters.
        /// </summary>
        /// <param name="queryString">
        /// The hql query.
        /// </param>
        /// <param name="paras">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<TE> Find(string queryString, params object[] values);


        /// <summary>
        /// Find by sql query
        /// </summary>
        /// <param name="sqlQuery"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        IList<TE> FindBySQLQuery(string sqlQuery, params object[] values);

        /// <summary>
        /// Find by sql query
        /// </summary>
        /// <param name="sqlQuery"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        IList<TC> FindBySQLQuery<TC>(string sqlQuery, params object[] values);

        /// <summary>
        /// Find by sql query
        /// </summary>
        /// <param name="sqlQuery"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        IList<TC> FindBySQLQuery<TC>(string sqlQuery, string[] names, object[] values);

        /// <summary>
        /// Find a list of entities by provide a named HQL and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<TE> FindByNamedQuery(string queryName, params object[] values);

        /// <summary>
        /// Find a list of entities by provide a named HQL and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<CT> FindCustomByNamedQuery<CT>(string queryName, params object[] values);

        /// <summary>
        /// Find a list of entities by provide a named HQL and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="names">
        /// The name of parameters.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<CT> FindCustomByNamedQuery<CT>(string queryName, string[] names, object[] values);

        /// <summary>
        /// Find a list of entities by provide a custom HQL and its parameters.
        /// </summary>
        /// <param name="queryString">
        /// The HQL query string.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<CT> FindCustomByHQLQuery<CT>(string queryString, params object[] values);

        /// <summary>
        /// Find a list of entities by provide a custom HQL and its parameters.
        /// </summary>
        /// <param name="queryString">
        /// The HQL query string.
        /// </param>
        /// <param name="names"></param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<CT> FindCustomByHQLQuery<CT>(string queryString, string[] names, object[] values);

        /// <summary>
        /// Find the first matched entity by providing an HQL and its parameters.
        /// </summary>
        /// <param name="query">
        /// The HQL query.
        /// </param>
        /// <param name="values">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entity or null if not found.
        /// </returns>
        TE FindOne(string queryString, params object[] values);

        /// <summary>
        /// Find one by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        TE FindOneByNamedQuery(string queryName, params object[] values);

        /// <summary>
        /// Find one by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        TE FindOneByNamedQuery(string queryName, string[] names, object[] values);

        /// <summary>
        /// Get number of matched entities by providing an HQL query and 
        /// its parameter values.
        /// </summary>
        /// <param name="queryString">
        /// The HQL query.
        /// </param>
        /// <param name="values">
        /// The query parameter values.
        /// </param>
        /// <returns>
        /// The number of matched entities.
        /// </returns>
        long GetCount(string queryString, params object[] values);

        /// <summary>
        /// Get SQL Count
        /// </summary>
        /// <param name="sqlString"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        long GetSqlCount(string sqlString, params object[] values);

        /// <summary>
        /// Get max by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        long GetMaxByNamedQuery(string queryName, params object[] values);

        /// <summary>
        /// Get max by named query.
        /// </summary>
        /// <param name="queryName"></param>
        /// <param name="names"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        long GetMaxByNamedQuery(string queryName, string[] names, object[] values);

        /// <summary>
        /// Delete an entity.
        /// </summary>
        /// <param name="entity">
        /// The entity to delete.
        /// </param>
        void Delete(TE entity);

        /// <summary>
        /// Delete a list of entity.
        /// </summary>
        /// <param name="entities">
        /// The entities to delete.
        /// </param>
        void DeleteAll(IList<TE> entities);

        /// <summary>
        /// Delete the entity by its key
        /// </summary>
        /// <param name="key">
        /// The entity key.
        /// </param>
        /// <returns>
        /// Number of affected entity ussual 
        /// </returns>
        int DeleteByKey(TK key);

        /// <summary>
        /// Delete entities by their keys
        /// </summary>
        /// <param name="keys">
        /// The entity keys
        /// </param>
        int DeleteByKeys(IList<TK> keys);

        /// <summary>
        /// Batch update entities by providing an HQL query and 
        /// its paramenter values
        /// </summary>
        /// <param name="queryString">
        /// The HQL query
        /// </param>
        /// <param name="paras">
        /// The query parameters
        /// </param>
        /// <returns>
        /// Number of affected entities
        /// </returns>
        int BatchUpdate(string queryString, params object[] values);

        /// <summary>
        /// Batch update entities by providing a named HQL query and
        /// its paramenter values
        /// </summary>
        /// <param name="queryName">
        /// The named HQL query
        /// </param>
        /// <param name="values">
        /// The query parameters
        /// </param>
        /// <returns>
        /// Number of affected entities
        /// </returns>
        int BatchUpdateByNamedQuery(string queryName, params object[] values);

        /// <summary>
        /// Batch stateless insert.
        /// </summary>
        /// <param name="entities">List of entities</param>
        void BatchStatelessInsert(IList<TE> entities);

        /// <summary>
        /// Batch stateless update.
        /// </summary>
        /// <param name="entities">List of entites</param>
        void BatchStatelessUpdate(IList<TE> entities);
    }
}
